package distributedRE.model;

import java.util.ArrayList;
import java.util.Hashtable;

import configuration.parameters.DoubleValuedParameter;
import configuration.parameters.Parameter;

public class QueryDatabase {
	
	private static Hashtable<String, QueryDatabase> qDb = new Hashtable<String, QueryDatabase>();
	
	private Query q;
	
	private DataBase db;
	
	private Hashtable<String, ArrayList<Parameter>> parameters;
	
	private ArrayList<Session> sessions;

	private DistributedREModel dREModel;
	
	private boolean selectable;

	public QueryDatabase(Query query, DataBase database,DistributedREModel dREModel) {
		
		q = query;
		
		db = database;
		
		selectable = true;
		
		this.dREModel = dREModel;
		
		parameters = new Hashtable<String, ArrayList<Parameter>>();
		
		sessions = new ArrayList<Session>();
		
	}

	public Parameter getParameter(String name) {

		ArrayList<Parameter> history = getParameterHistory(name);
		
		if (history.size() == 0)
			return null;
		
		return history.get(history.size()-1);
		
	}

	public ArrayList<Parameter> getParameterHistory(String name){

		ArrayList<Parameter> history = parameters.get(name);
		
		if (history == null)
			history = new ArrayList<Parameter>();
		
		return history;
		
	}
	
	public void addParameter(String name, Parameter parameter){

		ArrayList<Parameter> history = getParameterHistory(name);
		
		history.add(parameter);
		
		parameters.put(name, history);
		
	}

	public static QueryDatabase getInstance(Query query, DataBase database, DistributedREModel dREModel) {
		
		String key = generateKey(query,database,dREModel);
		
		QueryDatabase qdb = qDb.get(key);
		
		if (qdb!=null)
			return qdb;
		
		qdb = new QueryDatabase(query,database,dREModel);
		
		qDb.put(key, qdb);
		
		return qdb;
		
	}

	private static String generateKey(Query query, DataBase database, DistributedREModel dREModel) {
		
		String s = new String();
		
		s = query.getId() + "-" + database.getId() + "-" + dREModel.getId();
		
		return s;
	}
	
	public void addSession(Session s){
		
		sessions.add(s);
		
	}

//	public DataBase getDatabase() {
//		
//		return db;
//	
//	}
	
	public int getNumberOfSessions(){
		
		return sessions.size();
	
	}

	public Query getQuery() {
		
		return q;
		
	}
	
	public boolean equals(Object o){
		QueryDatabase qdb = (QueryDatabase)o;
		
		return (db.equals(qdb.db) && getQuery().equals(qdb.getQuery()) && dREModel.equals(qdb.dREModel));
	}

	public long getNumberOfDocuments() {
		
		long total = db.getNumberOfDocuments();
		
		double processed = getProcessedDocuments();
				
		return total - (long)processed;
		
	}

	private double getProcessedDocuments() {

		double processed = 0;
		
		DoubleValuedParameter dvp = (DoubleValuedParameter) getParameter(Parameter.TOTAL_DOCUMENTS_PROCESSED);
		
		if (dvp!=null){
			
			processed = ((Double)dvp.getValue()).doubleValue();
			
		}
		
		return processed;
	}

	public long getFrequency(String term, boolean updated) {
		
		long freq = db.getFrequency(term);
		
		double processed = 0;
		
		if (updated)
			processed = getProcessedDocuments();
		
		return freq - (long)processed;
		
	}
	
	public boolean isSelectable() {
		return selectable;
	}

	public void setSelectable(boolean selectable) {
		this.selectable = selectable;
	}
	
}
